#include "RenderingThreadBody.h"
#include "RunnableTask.h"
#include "RunnableTaskEvent.h"
#include "Runtime/Debug/Logger.h"
#include "Platform/PlatformAPI.h"

bool IsInRenderingThread()
{
	return FPlatformTLS::GetCurrentThreadId() == BattleFire::WorkerThread::RenderThreadID;
}
namespace BattleFire
{
	RenderingThreadBody * GRenderingThreadContext=nullptr;
	WorkerThread*GRenderingThread=nullptr;
	bool GIsRunningRHIInSeparateThread_InternalUseOnly=false;
	bool FORCEINLINE IsRunningRHIInSeparateThread()
	{
		return GIsRunningRHIInSeparateThread_InternalUseOnly;
	}
	static int32 FlushRHILogsAndReportCrash(LPEXCEPTION_POINTERS ExceptionInfo)
	{
		return 0;
	}
	/** The rendering thread main loop */
	void RenderingThreadMain( BattleFireEvent* RenderThreadContextReadyEvent)
	{
		//let the main thread go, wait for render thread init complete to trigger event
		std::this_thread::sleep_for(std::chrono::microseconds(16));
		ENamedThreads RenderThread = ENamedThreads::ActualRenderingThread;
		SetRenderThread(RenderThread);
		SetRenderThread_Local(ENamedThreads::ActualRenderingThread_Local);
		ThreadPoolInterface::Get().AttachToThread(RenderThread);
		if(RenderThreadContextReadyEvent != NULL )
		{
			RenderThreadContextReadyEvent->TriggerOne();
		}
		ThreadPool::Get().ProcessThreadUntilRequestReturn(RenderThread);
		SetRenderThread(ENamedThreads::GameThread);
		SetRenderThread_Local(ENamedThreads::GameThread_Local);
	}
	bool RenderingThreadBody::Init() {
		WorkerThread::RenderThreadID = FPlatformTLS::GetCurrentThreadId();
		BOOL Result = wglMakeCurrent(OpenGLDevice::mCurrentOpenGLDevice.mHandleDeviceContext, OpenGLDevice::mCurrentOpenGLDevice.mRenderContext);
		if (!Result)
		{
			Error("RenderingThreadBody::Init %d %p %p Failed[%d] %p,%p\n", 
				WorkerThread::RenderThreadID, 
				OpenGLDevice::mCurrentOpenGLDevice.mHandleDeviceContext, 
				OpenGLDevice::mCurrentOpenGLDevice.mRenderContext,
				GetLastError(),wglGetCurrentDC(),wglGetCurrentContext());
		}
		return true;
	}
	uint32 RenderingThreadBody::Run()
	{
		__try
		{
			RenderingThreadMain(ReadyEvent);
		}
		__except(FlushRHILogsAndReportCrash(GetExceptionInformation()))
		{
		}
		return 0;
	}

    void StartRenderingThread()
	{
		GRenderingThreadContext = new RenderingThreadBody();
    	GRenderingThread=WorkerThread::Create("RenderThread",GRenderingThreadContext);
		GRenderingThreadContext->ReadyEvent->Wait();
	}


	void StopRenderingThread()
	{
		RunnableTaskEventRef QuitTask = TRunnableTask<FReturnGraphTask>::CreateTask(NULL, ENamedThreads::GameThread).ConstructAndDispatchWhenReady(GetRenderThread());
		while ((QuitTask!= nullptr) && !QuitTask->IsComplete())
		{
			BattleFireSleep(0);
		}
		GRenderingThread->WaitForCompletion();
		delete GRenderingThread;
		GRenderingThread = nullptr;
		delete GRenderingThreadContext;
		GRenderingThreadContext = nullptr;
	}
}
